package com.heima.search.service.impl;

import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ArticleSearchServiceImpl implements ArticleSearchService {


    @Autowired
    RestHighLevelClient client;

    @Autowired
    ApUserSearchService apUserSearchService;

    /**
     * ES文章分页搜索
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult search(UserSearchDto dto) {
        //1 参数检查
        if (dto == null || StringUtils.isBlank(dto.getSearchWords())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 时间校验
        if (dto.getMinBehotTime() == null) {
            dto.setMinBehotTime(new Date());
        }
        //分页检查
        if (dto.getPageSize() <= 0 || dto.getPageSize() > 10) {
            dto.setPageSize(10);
        }

        ApUser user = AppThreadLocalUtils.getUser();

        // 异步记录搜索关键词
        if (user != null && dto.getFromIndex()==0) {  // 首页记录
            //  记录关键词
            dto.setEntryId(user.getId());
            apUserSearchService.insert(dto);
        }



        try {

            //2 构建查询条件
            SearchSourceBuilder builder = new SearchSourceBuilder();

            // bool 查询
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // title
            MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("title", dto.getSearchWords());
            boolQuery.must(matchQuery);

            // 时间过滤（上拉）
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime")
                    .lte(dto.getMinBehotTime());
            boolQuery.filter(rangeQueryBuilder);

            // 分页
            builder.size(dto.getPageSize());
            builder.from(0);  // 默认值

            // 高亮 三要素
            builder.highlighter(SearchSourceBuilder.
                    highlight().field("title")
                    .preTags("<font style='color:red'>")
                    .postTags("</font>"));

            // sort 排序 发布时间倒序
            builder.sort("publishTime", SortOrder.DESC);


            //3 执行查询
            SearchRequest request = new SearchRequest("app_info_article");

            // *********
            builder.query(boolQuery);

            request.source(builder);

            // ****
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);

            //4 封装结果
            SearchHits hits = response.getHits();
            long total = hits.getTotalHits().value;
            System.out.println("总记录：" + total);

            // 返回数据
            List<Map> resultList = new ArrayList<>();

            SearchHit[] searchHits = hits.getHits();
            for (SearchHit searchHit : searchHits) {

                // 原始数据
                Map<String, Object> articleMap = searchHit.getSourceAsMap();

                // 高亮结果
                HighlightField highlightField = searchHit.getHighlightFields().get("title");

                // 保留原始不带高亮的标题
                articleMap.put("o_title", articleMap.get("title"));

                String htitle = StringUtils.join(highlightField.fragments());
                if (StringUtils.isNotBlank(htitle)) {
                    articleMap.put("title", htitle);
                }

                resultList.add(articleMap);
            }


            //5 返回
            return ResponseResult.okResult(resultList);

        } catch (IOException e) {
            e.printStackTrace();
        }


        return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
    }

}

